android聊天,存储聊天记录sqlite
项目中有聊天模块,需要用到打开activity的时候初始化聊天记录的情况。大致情况如下:
辅助类:ChatSQLiteHelper 在第一次时会调用oncreate方法(判断的标准是schedule.db里面会存储是否已经新建过,若没有,则会调用onCreate,只会调用一次)
package com.example.qurenwu.chat; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteDatabase.CursorFactory; public class ChatSQLiteHelper extends SQLiteOpenHelper{ //调用父类构造器 public ChatSQLiteHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } /** * 当数据库首次创建时执行该方法,一般将创建表等初始化操作放在该方法中执行. * 重写onCreate方法,调用execSQL方法创建表 * */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE chat (id INTEGER PRIMARY KEY,"+ "user_id varchar(64), "+ "friend_id varchar(64), "+ "contentChat varchar(255), typeChat varchar(8), "+ "postdateChat DATETIME, "+ "isreadChat integer,"+ "ismineChat integer NOT NULL DEFAULT (0),"+ "deleteChat integer);"); } //当打开数据库时传入的版本号与当前的版本号不同时会调用该方法 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
以下是使用方法(由于赶时间,下面的代码都是在activity中的页面代码中)
package com.example.qurenwu.qurenwu_2.chat; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.database.ContentObserver; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import com.example.qurenwu.qurenwu_2.R; import com.example.qurenwu.qurenwu_2.custom.GotaskGlobalVal; import com.example.qurenwu.qurenwu_2.thread.UserHttpThread; import org.json.JSONException; import org.json.JSONObject; public class ChatPageActivity extends Activity implements OnClickListener{ private ImageView back; private Button mBtnSend; private EditText mEditTextContent; private ListView mTalkView; private ChatMsgAdapter mAdapter; private List<ChatMsgEntity> mDataArrays = new ArrayList<ChatMsgEntity>(); private GotaskGlobalVal globalVal; UserHttpThread userHttpThread; private String myuser_id,friend_id; private String friend_head_image_url; //对方头像 private String my_head_image_url; //我的头像 DisplayMetrics dm; int dmwidth; SocketThread st; public DataInputStream dis = null; public DataOutputStream dos = null; Handler handler; SQLiteOpenHelper openHelper; private final int REV_MSG = 1; //接收消息 private final int REQUEST_MINE_HEADURL = 2; //获取我的头像url public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat_page); getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); //软键盘 //获取手机屏幕像素 dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); dmwidth = dm.widthPixels; globalVal = (GotaskGlobalVal) getApplicationContext(); back = (ImageView)findViewById(R.id.back); back.setOnClickListener(this); //接收好友对象资料 Intent intent = getIntent(); friend_id = intent.getStringExtra("friend_id"); friend_head_image_url = intent.getStringExtra("friend_head_image"); //获取对方头像url my_head_image_url = intent.getStringExtra("my_head_image"); //获取自己头像url Log.v("获取头像:","对方头像"+friend_head_image_url+";我的头像:"+my_head_image_url); myuser_id = globalVal.GetUserID(); handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case REV_MSG://处理接收到的消息 String str = msg.obj.toString(); try { int forend = str.indexOf(config.PROTOCOL_FOR_END); //解析str if(forend>0) { String fromname = str.substring(str.indexOf(config.PROTOCOL_COME) + 1, str.indexOf(config.PROTOCOL_COME_END)); String forname = str.substring(str.indexOf(config.PROTOCOL_FOR) + 1, str.indexOf(config.PROTOCOL_FOR_END)); String _date = str.substring(str.indexOf(config.PROTOCOL_DATE) + 1, str.indexOf(config.PROTOCOL_DATE_END)); String forchat = str.substring(str.indexOf(config.PROTOCOL_DATE_END) + 1); ChatMsgEntity entity = new ChatMsgEntity(); entity.setDate(_date); entity.setName(fromname); entity.setText(forchat); entity.setMsgType(true); mDataArrays.add(entity); mAdapter.notifyDataSetChanged(); mTalkView.setSelection(mDataArrays.size()-1); Log.v("Handle接收到的消息",forchat); } } catch (Exception ex) {} break; case REQUEST_MINE_HEADURL: break; } } }; initView(); //1、从本地sqlite数据库获取历史数据 //首次进入,先把聊天记录调出 initdb(); readChat(); //2、socket连接服务器 chatContent(); new Thread(new ReceiveThread()).start(); } //初始化界面 public void initView() { mTalkView = (ListView) findViewById(R.id.listview); mBtnSend = (Button) findViewById(R.id.btn_send); mBtnSend.setOnClickListener(this); mEditTextContent = (EditText) findViewById(R.id.et_sendmessage); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.back: openHelper.close(); finish(); break; case R.id.btn_send: send(); break; } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && ((FaceRelativeLayout) findViewById(R.id.FaceRelativeLayout)) .hideFaceView()) { Log.v("onKeyDown","表情FaceRelativeLayout"); return true; } return super.onKeyDown(keyCode, event); } private void send() { String contString = mEditTextContent.getText().toString(); //更新界面 if (contString.length() > 0) { ChatMsgEntity entity = new ChatMsgEntity(); entity.setDate(getDate()); entity.setMsgType(false); entity.setText(contString); entity.setHeadImg(my_head_image_url); mDataArrays.add(entity); mAdapter.notifyDataSetChanged(); mEditTextContent.setText(""); mTalkView.setSelection(mTalkView.getCount() - 1); } //发送socket消息 DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String date = df.format(new Date()); try { if(dos!=null){ dos.writeUTF(config.PROTOCOL_KEY+config.PROTOCOL_FOR + friend_id + config.PROTOCOL_FOR_END +myuser_id+"end;"+contString); //将发送的消息存入本地 ContentValues con = new ContentValues(); con.put("fromChat", friend_id); con.put("nameChat", myuser_id); con.put("contentChat", contString); con.put("typeChat", "text"); con.put("postdateChat", date); con.put("isreadChat", "1"); con.put("ismineChat", "1"); con.put("deleteChat", "0"); //getContentResolver().insert(DataChangeProvider.CONTENT_URI, con); //保存到本地sqlite SQLiteDatabase db=openHelper.getReadableDatabase(); ContentValues values = new ContentValues(); values.put("user_id",myuser_id); values.put("friend_id",friend_id); values.put("contentChat",contString); values.put("typeChat","text"); values.put("postdateChat",date); values.put("isreadChat",1); values.put("ismineChat",1); db.insert("chat",null,values); db.close(); }else{ Toast.makeText(ChatPageActivity.this, "连接超时,服务器未开放或IP错误,dos is null", Toast.LENGTH_LONG).show(); } }catch (SocketTimeoutException e) { System.out.println("连接超时,服务器未开放或IP错误"+e.getMessage()); Toast.makeText(ChatPageActivity.this, "连接超时,服务器未开放或IP错误", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("连接超时,服务器未开放或IP错误"+e.getMessage()); Toast.makeText(ChatPageActivity.this, "连接超时,服务器未开放或IP错误", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } private String getDate() { Calendar c = Calendar.getInstance(); String year = String.valueOf(c.get(Calendar.YEAR)); String month = String.valueOf(c.get(Calendar.MONTH)); String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH) + 1); String hour = String.valueOf(c.get(Calendar.HOUR_OF_DAY)); String mins = String.valueOf(c.get(Calendar.MINUTE)); StringBuffer sbBuffer = new StringBuffer(); sbBuffer.append(year + "-" + month + "-" + day + " " + hour + ":" + mins); return sbBuffer.toString(); } //子线程连接服务器socket public void chatContent(){ new Thread(){ public void run () { try { st = new SocketThread(); st.SocketStart(config.SERVER_IP, config.SERVER_PORT, friend_id); if(st.isConnected()){ dos = st.getDOS(); dis = st.getDIS(); dos.writeUTF(config.PROTOCOL_KEY+config.PROTOCOL_ONLINE+myuser_id); dos.flush(); dos.writeUTF(config.PROTOCOL_KEY+config.PROTOCOL_WAIT+myuser_id); dos.flush(); } }catch (UnknownHostException e) { System.out.println("连接失败"); Toast.makeText(ChatPageActivity.this, "连接失败", Toast.LENGTH_SHORT).show(); e.printStackTrace(); }catch (SocketTimeoutException e) { System.out.println("连接超时,服务器未开放或IP错误"); Toast.makeText(ChatPageActivity.this, "连接超时,服务器未开放或IP错误", Toast.LENGTH_SHORT).show(); e.printStackTrace(); }catch (IOException e) { System.out.println("连接失败"); e.printStackTrace(); } } }.start(); } private class ReceiveThread implements Runnable { public void run() { try { while (true) { try { String str = dis.readUTF(); Message msg = new Message(); msg.what = REV_MSG; msg.obj = str; handler.sendMessage(msg); } catch (NullPointerException ex) {} } } catch (SocketException e) { System.out.println("SocketException"); } catch (IOException e) { e.printStackTrace(); } } } private void RequestUserInfo(String user_id) { Map<String,String> param = new HashMap<String, String>(); param.put("datatype","5"); param.put("user_id",user_id); userHttpThread = new UserHttpThread(handler,param,REQUEST_MINE_HEADURL); new Thread(userHttpThread).start(); } private void initdb() { //准备数据库,存取聊天记录 openHelper=new ChatSQLiteHelper(this,"chat.db",null,1) ; } private void readChat(){ String _date; String _text; String _isreadChat; String _ismineChat; //0:对方的消息 1:自己发送的消息 boolean _isComMeg = true; //获取数据库中的信息 SQLiteDatabase db=openHelper.getReadableDatabase(); String sql="select contentChat,postdateChat,isreadChat,ismineChat from chat where user_id=? and friend_id=?"; Cursor c = db.rawQuery(sql,new String[]{globalVal.GetUserID(),friend_id}); while(c.moveToNext()){ _text=c.getString(0); _date=c.getString(1); _isreadChat=c.getString(2); _ismineChat=c.getString(3); Log.v("ceshi", _text+_date+_isreadChat); ChatMsgEntity entity = new ChatMsgEntity(); entity.setText(_text); entity.setDate(_date); if(_ismineChat!=null && _ismineChat.equals("0")){_isComMeg= false;} entity.setMsgType(_isComMeg); entity.setHeadImg(_isComMeg?my_head_image_url:friend_head_image_url); mDataArrays.add(entity); } mAdapter = new ChatMsgAdapter(this, mDataArrays,mTalkView); mTalkView.setAdapter(mAdapter); mTalkView.setSelection(mTalkView.getCount() - 1); db.close(); } }
说一下我当时遇到的问题:
1、sqlite出现no such table chat ,原因:没有调用ChatSQLiteHelper的Oncreate方法,因为我在activity中有重写了ChatSQLiteHelper的Oncreate方法
如下:
openHelper=new ChatSQLiteHelper(this,"chat.db",null,1) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public void onCreate(SQLiteDatabase db) { //这里是空的,什么事情都没做,所以也就不会新建chat表了 } }
2、出现 android_meta***忘记了,反正纠结在数据库的路径这一块,下面大略写出来对比一下
之前错误的写法:
private SQLiteDatabase openDateBase(String dbFile) //dbFile是我自己命名的一个路径:/data/data/你的报名/databases/chat.db { File file = new File(dbFile); if (!file.exists()) { // // 打开raw中得数据库文件,获得stream流 InputStream stream = this.mContext.getResources().openRawResource(R.raw.chat); //该目录下也放了一个自己导出来的chat.db,所以不能这么做,自己都晕了 try { // 将获取到的stream 流写入道data中 FileOutputStream outputStream = new FileOutputStream(dbFile); .... } } }
现在的写法:
openHelper=new ChatSQLiteHelper(this,"chat.db",null,1) ; //直接调用,默认ChatSQLiteHelper创建的路径,真实地址应该是:/data/data/你的报名/databases/ 这个目录下面